#第六部分 元编程
#第十九章 动态属性和特性
from urllib.request import urlopen
from collections import abc
import os,json
import warnings
import keyword #关键字模块


ROOT = os.path.split(__file__)[0]
URL = 'http://www.oreilly.com/pub/sc/osconfeed'
jsonFile = os.path.join(ROOT,"downloads",'osconfeed.json')

def load():
    if not os.path.exists(jsonFile):
        with urlopen(URL) as remote,open(jsonFile,'wb') as fb:
            fb.write(remote.read())
    with open(jsonFile,encoding='utf8') as fb:
        data = json.load(fb)
    return data



class FrozenJSON():
    def __init__(self,data)->None:
        self.__data = {}
        for key,val in data.items():
            if keyword.iskeyword(key): #处理特殊键名
                key+="_"            
            self.__data[key] = val
    
    def __getattr__(self,name):        
        if hasattr(self.__data,name):
            print("hasattr",name)
            return getattr(self.__data,name)
        else:
            print("hasattr build",name)
            return FrozenJSON.build(self.__data[name])
        
    @classmethod
    def build(cls,obj):        
        if isinstance(obj,abc.Mapping): #映射类 键值对            
            return cls(obj)
        elif isinstance(obj,abc.MutableSequence): #序列类 下标获取            
            return [cls.build(item) for item in obj]
        else:           
            return obj


'''
d = load() 
print(type(d))

#Schedule
obj = FrozenJSON(d)
print(obj.Schedule.keys())

s = "name"
print(s.isidentifier()) #判断该字符串是否是有效的标识符 
s = '12name' #标识符不能以数字开头
print(s.isidentifier())
'''